use log;
#[allow(unused)]
use colored::Colorize;
use std::process::Command;
use chrono::Local;
use std::io::Write;
use std::fs;

use std::io::ErrorKind;
use std::io::Error as IOError;
use std::path;

use crate::special::Special;
use crate::special::NetStr;
// type Out<T> = Result<T, Error>;
pub type IoOut<T> = Result<T, IOError>;

#[allow(dead_code)]
pub fn log_inif(){
    let mut clog = colog::builder();
    clog.format(|buf, record| {
            writeln!(buf,
                "{} [{}] - {}",
                Local::now().format("%Y-%m-%dT%H:%M:%S"),
                record.level(),
                record.args()
            )
    });
    // clog.filter(None, log::LevelFilter::Warn);
    clog.init();
}

#[allow(dead_code)]
fn run_shell(cmd:&str) -> IoOut<()>{
    let stdout = if cfg!(target_os="windows"){
        Command::new("cmd")
            .arg("/C")
            .arg(format!("{}", cmd))
            .output()?
    }else{
        Command::new("sh")
        .arg("-c")
        .arg(format!("{}", cmd))
        .output()?
    };
    if stdout.status.success(){
        log::info!("run : {} [{}]", cmd, "ok");
        Ok(())
    }else{
        Err(IOError::new(ErrorKind::Other, "run failed"))
    }
}

#[allow(dead_code)]
pub fn create_project(pro_path:&str) -> IoOut<String>{
    let p = path::Path::new(pro_path);
    // let _ = p.file_name().unwrap().to_str().unwrap();
    match run_shell(&format!("cargo new --bin {}", p.to_str().unwrap())){
        Ok(_) => {
            // let project_root = path::Path::new(name);
            Ok(p.to_str().unwrap().to_string())
        },
        Err(e) => {
            log::error!("{} {} ", &format!("{}",e).red(),pro_path);
            Err(IOError::new(ErrorKind::Other, "create failed "))
        }
    }
}

#[allow(dead_code)]
pub fn create_template(project_root:&path::Path) -> IoOut<()>{
    let view_root = project_root.join("src").join("template");
    let pro_name = project_root.file_name().unwrap().to_str().unwrap();
    fs::create_dir(&view_root)?;
    let root_str = view_root.to_str().unwrap().to_string();
    
    let download_deafult_res = |tt:String, name:&str| {
        
        let r = path::Path::new(&tt);
        // let nn = if cfg!(target_os="windows"){
        //     name.to_string().replace("/","\\")
        // }else{
        //     name.to_string()
        // };
        let nn = name.to_string();
        match format!("https://gitee.com/dark.H/r-ui/raw/master/src/template/{}", name)
            .download_to(r.join(&nn).to_str().unwrap()){
                Ok(_) => {},
                Err(e) => {
                    log::error!("down {}|{}",name,&format!("{}",e).red());
                }
            };
    };
    // let a = std::sync::Arc::new(9);
    let (tx,rx) = std::sync::mpsc::channel::<i32>();
    let res_list = ["default.js",
                    "jquery.min.js",
                    "base64.min.js",
                    "ie.js",
                    "log.js",
                    "light.css",
                    "highlight.js",
                    "progress.html",
                    "default.css",
                    "bootstrap-4/js/bootstrap.min.js",
                    "bootstrap-4/css/bootstrap.min.css"
    ];
    let mut counter = res_list.len() as i32;
    for name in res_list.iter(){
        let tmp_n = name.to_string();
        let tt = root_str.clone();
        let tx_s = tx.clone();
        std::thread::spawn(move || {
            // Arc::clone(d)
            let m = tmp_n.clone();
            
            download_deafult_res(tt.clone(),&m);
            tx_s.send(1).expect("send failed");
        });
    }

    loop {
        let s = rx.recv().expect("recv faied");
        counter -= s;
        if counter == 0{
            break
        }
    }

    "https://gitee.com/dark.H/r-ui/raw/min/src/view.rs".download_to(
        project_root.join("src").join("view.rs").to_str().unwrap())?;
    // std::thread::sleep(std::time::Duration::from_secs(3))
    // "".download_to()
    
    let _ = project_root.join("src").join("main.rs").write_all(r#"
    #[macro_use]
    extern crate serde_derive;
    #[macro_use]
    extern crate lazy_static;
    extern crate web_view;
    extern crate threadpool;
    extern crate serde_json;
    extern crate base64;
    extern crate crossbeam;
    extern crate crossbeam_channel;
    mod view;
    use view::UI;
    fn main() {
        r_ui::log_init();
        let mut h = with_html! {@li UI
            (T "hello world"),
            (T "hello world"),
            (T "hello world")
            @css
            ul {
                height: 80%;
            }
        };
        let res = view::load_res_files("src/template/light.css
        src/template/default.css
        src/template/bootstrap-4/css/bootstrap.min.css
        src/template/base64.min.js
        src/template/jquery.min.js
        src/template/bootstrap-4/js/bootstrap.min.js
        src/template/highlight.js
        src/template/default.js
        ");
        view::app_with(&h, res,  move |_, _| loop {});
    }
    "#);
    let _ = project_root.join("Cargo.toml").write_all(&format!(r#"
[package]
name = "{name}"
version = "0.1.0"
authors = ["xxx"]
edition = "2018"

[dependencies]
r-ui = ++git="https://gitee.com/dark.H/r-ui.git"--
web-view = "0.5.2"
lazy_static = "1.4.0"
clap = ++git= "https://github.com/clap-rs/clap.git"--
log = "0.4.8"
serde_json = "1.0"
colored = "1.8"
threadpool = "1.7.1"
crossbeam = "0.7"
serde = "1.0"
serde_derive = "1.0"
crossbeam-channel = "0.3"
base64 = "0.11.0"
    "#, name=pro_name).replace("++","{").replace("--","}"));
    Ok(())
}

